// DrCode2
package main

type DrSource struct {
	module    string
	lines     []string
	tokenList []string
	tokens    []string
	Cvalue    int //记录圆括号
	Hvalue    int //记录大括号
	Svalue    int //记录方括号
	brackets  BracketStack
}

func (code *DrSource) AddToken(token string) {
	code.tokens = append(code.tokens, token)
}

//将字符串进行扫描，分离出变量名、括号、关键词等
func (code *DrSource) Scan3(line string, start int) (int, bool) {
	code.tokenList = make([]string, 0, 100)
	CurLine := line[0:]
	var name string
	for {
		if len(CurLine) == 0 {
			break
		}

		//找到一个操作符后，下面不一定就是一个括号这样的符号，还有可能是变量，所以会导致错误
		// if no operator is found, to test whether is other symbols
		char, start := findNextChar(CurLine, 0)
		CurLine = CurLine[start:]
		// Char := string(char)
		// fmt.Println(Char)

		if IsNumAndChar(char) { //如果当前字符属数字及字母，则把它当作Name的一部分
			if len(code.tokens) > 0 {
				lastToken := code.tokens[len(code.tokens)-1]
				if lastToken == ")" || lastToken == "]" || lastToken == "}" {
					panic("number or name cannot be put here")
				}
			}
			name, start = findNextName(CurLine, 0)
			CurLine = CurLine[start:]
			code.AddToken(name)
			continue
		}
		//如果当前char不是数字或字母，那就看它是否是运算符的一部分
		name, start = findNextOperator(CurLine, 0)
		operaterName := name
		//CurLine = CurLine[start+1:]
		if operaterName == "[]" {
			code.AddToken("list")
			code.AddToken("(")
			code.AddToken(")")
			CurLine = CurLine[start:]
			continue
		}
		if operaterName != "" { //如果是合法运算符，则将运算符加入token列表
			code.AddToken(operaterName)
			CurLine = CurLine[start:]
			continue
		}

		// if char == '.' {
		// 	code.Hvalue += 1
		// 	code.AddToken(".")
		// 	CurLine = CurLine[start+1:]
		// 	continue
		// }
		//如果在当前行没找到运算符，则判断char是不是下列符号

		if char == '{' {
			code.Hvalue += 1
			code.AddToken("{")
			CurLine = CurLine[start+1:]
			code.brackets.push(char)
			continue
		} // end (
		if char == '}' {
			if code.Cvalue > 0 {
				panic("')' is expected, but encoutered a '}'")
			}
			if code.Svalue > 0 {
				panic("']' is expected, but encoutered a '}'")
			}
			code.Hvalue -= 1
			code.AddToken("}")
			CurLine = CurLine[start+1:]
			if code.brackets.top() == '{' {
				code.brackets.pop()
			} else {
				panic("'" + string(code.brackets.top()) + "' is need to be closed, but ’}’ is encountered")
			}
			continue
		} // end (
		if char == '(' {
			code.Cvalue += 1
			code.AddToken("(")
			CurLine = CurLine[start+1:]
			code.brackets.push(char)
			continue
		} // end (

		if char == ',' {
			lastToken := code.tokens[len(code.tokens)-1]
			if lastToken == "(" || lastToken == "{" || lastToken == "[" || IsOperator(lastToken) {
				panic("',' cannot put here")
			}
			if lastToken == ":" {
				code.AddToken("ENDINDEX")
			}
			code.AddToken(",")
			CurLine = CurLine[start+1:]
			continue
		} //end ,

		if char == ')' {
			code.Cvalue -= 1
			code.AddToken(")")
			CurLine = CurLine[start+1:]
			if code.brackets.top() == '(' {
				code.brackets.pop()
			} else {
				panic("'" + string(code.brackets.top()) + "' is need to be closed, but ’)’ is encountered")
			}
			continue
		} // end )
		if char == ':' {
			lastToken := code.tokens[len(code.tokens)-1]
			if lastToken == "," || lastToken == "[" { //如果在:前面是逗号或‘[’，则补个0
				code.AddToken("0")
			}
			code.AddToken(":")
			CurLine = CurLine[start+1:]
		}
		if char == '\n' || char == ';' || char == '\r' || char == 0 {
			code.AddToken("\n")
			CurLine = CurLine[start+1:]
			continue
		}
		if char == '\'' {
			code.AddToken("'")
			str, start := findNextString(CurLine)
			CurLine = CurLine[start:]
			code.AddToken(str)
			code.AddToken("'")
			continue
		}
		if char == '"' {
			code.AddToken("\"")
			str, start := findNextString(CurLine)
			CurLine = CurLine[start:]
			code.AddToken(str)
			code.AddToken("\"")
			continue
		}
		if char == '[' {
			lastToken := code.tokens[len(code.tokens)-1]
			if IsValidVarName(lastToken) || lastToken == ")" || lastToken == "]" { //如果前一个token是变量名或者是‘)’，则按[]符号对待，否则按list对待
				code.AddToken("[")
				code.Svalue += 1
			} else {
				code.AddToken("list")
				code.AddToken("(")
				//code.Svalue += 1
			}
			code.brackets.push(char)
			CurLine = CurLine[start+1:]
			continue
		} // end )
		if char == ']' {
			if code.Svalue > 0 {
				lastToken := code.tokens[len(code.tokens)-1]
				if lastToken == ":" {
					code.AddToken("ENDINDEX")
				}
				code.AddToken("]")
				code.Svalue -= 1
			} else {
				code.AddToken(")")
				//code.Svalue -= 1
			}
			if code.brackets.top() == '[' {
				code.brackets.pop()
			} else {
				panic("'" + string(code.brackets.top()) + "' is need to be closed, but ’]’ is encountered")
			}
			CurLine = CurLine[start+1:]
			continue
		} // end )

	} //end for
	code.AddToken("\n") //末尾补加一个换行符
	//补充处理
	for i := 1; i < len(code.tokens); i++ {
		tok := code.tokens[i]
		pre := code.tokens[i-1]
		if tok == "list" && (IsValidVarName(pre) || pre == ")") {
			code.tokens[i] = "[]"
		}
	}

	return start, true
}

func NewSource(module string) *DrSource {
	code := new(DrSource)
	code.module = module[:len(module)-4]
	reader := NewTxtReader(module)
	code.lines = reader.ReadLines()
	reader.Close()
	for _, line := range code.lines {
		if line == "\n" || line == "" {
			continue
		}
		code.Scan3(line, 0)
	}
	return code
}
